﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Text.RegularExpressions;

//计算表达式 a+b-c+b
namespace Interpreter
{
    //抽象类用来计算表达式
    public abstract class Expression
    {
        public abstract float Call(Dictionary<string, float> keyValues);
    }

    //变量解析器
    public class VarExpression : Expression
    {
        private string key;
        public VarExpression(string key)
        {
            this.key = key;
        }
        public override float Call(Dictionary<string, float> keyValues)
        {
            if (keyValues.ContainsKey(this.key))
            {
                return keyValues[key];
            }
            return int.MinValue;
        }
    }
    /// <summary>
    /// 运算符解释器
    /// </summary>
    public class OPerationParer
    {
        private Expression expression;
        public OPerationParer(string expStr)
        {
            //0. 获取最高优先等级
            int topOperNu = AssemClass.GetTopPriorityVal(expStr);
            if (topOperNu == 0)
            {
                throw new Exception("表达式中至少要包含一个运算符！");
            }
            Regex regex = new Regex("^[a-zA-Z]$");
            bool IsFirst = true;
            string itemChar = string.Empty;
            Stack<Expression> stackExpAll = new Stack<Expression>();
            for (int i = 0; i < expStr.Length; i++)
            {
                itemChar = expStr[i].ToString();
                if (regex.IsMatch(itemChar))
                {
                    stackExpAll.Push(new VarExpression(itemChar));
                    if (IsFirst)
                    {
                        IsFirst = false;
                    }
                }
                else
                {
                    if (IsFirst)
                    {
                        throw new Exception("传入参数错误，表达式不能以运算法开头！！");
                    }

                    stackExpAll.Push(new OperCharExpression(itemChar));
                }
            }

            for (int i = topOperNu; i > 0; i--)
            {
                //1. 临时变量初始化 堆栈
                Stack<Expression> stackExp = new Stack<Expression>();
                Expression left = null;
                Expression right = null;
                Expression itemExp = null;
                var arrExpress =  stackExpAll.ToArray();
                Array.Reverse(arrExpress);
                for (int j=0;j < arrExpress.Length; j++)
                {
                    itemExp = arrExpress[j];
                    //判断是否操作符号
                    if (itemExp is OperCharExpression)
                    {
                        string operStr = ((OperCharExpression)itemExp).OperChar;
                        //判断是否是当前操作等级
                        if (i == AssemClass.GetCurPriortyVal(operStr))
                        {
                            left = stackExp.Pop();
                            j++;
                            right = arrExpress[j];
                            object[] objs = new object[] { left, right };
                            stackExp.Push(AssemClass.GetTypeByName<Expression>(operStr, objs));
                        }
                        else
                        {
                            stackExp.Push(itemExp);
                        }
                    }
                    else
                    {
                        stackExp.Push(itemExp);
                    }
                }
                stackExpAll = stackExp;
            }

            this.expression = stackExpAll.Pop();
        }

        //计算最终结果
        public float CallResult(Dictionary<string, float> corresDic)
        {
            if (this.expression != null)
            {
                return this.expression.Call(corresDic);
            }
            return float.MinValue;
        }
    }

}
